import * as vscode from "vscode";
import * as fs from "fs";
import { DatabaseParam, HighlightjsParam, LocalModelMessage, ModelInfoParam, ProjectTemplateParam, Task } from "./types";
import * as path from 'path';

export const GlobalFileNames = {
	modelInfo: "model-info.json",
	history: "history.json",
	settings: "settings.json",
	database: 'database.json',
	projectTemplate: 'project-template.json',
	highlightjs: 'highlightjs.json'
};

export class GlobalStore {
	dir: vscode.Uri;
	constructor(context: vscode.ExtensionContext) {
		this.dir = context.globalStorageUri;
	}

	getDatabase(): DatabaseParam {
		const dbFileUri = vscode.Uri.joinPath(this.dir, GlobalFileNames.database);
		this.checkFileDir(dbFileUri);
		if(fs.existsSync(dbFileUri.fsPath )) {
			const data = fs.readFileSync(dbFileUri.fsPath );
			return JSON.parse(data.toString());
		}
		return {
			type: 'mysql',
			connectionString: 'mysql://root:password@localhost:3306',
			mode: 'admin'
		};
	}

	getModelInfo(): ModelInfoParam {
		const modelInfoFileUri = vscode.Uri.joinPath(this.dir, GlobalFileNames.modelInfo);
		this.checkFileDir(modelInfoFileUri);
		if(fs.existsSync(modelInfoFileUri.fsPath )) {
			const data = fs.readFileSync(modelInfoFileUri.fsPath );
			return JSON.parse(data.toString());
		}
		return {
			modelName: 'deepseek/deepseek-chat',
			baseUrl: 'https://api.deepseek.com/v1',
			apiKey: '',
			maxTokens: (64 * 1024).toString(),
			temperature: '0'
		};
	}

	getProjectTemplate(): ProjectTemplateParam {
		const projectTemplateFileUri = vscode.Uri.joinPath(this.dir, GlobalFileNames.projectTemplate);
		this.checkFileDir(projectTemplateFileUri);
		if(fs.existsSync(projectTemplateFileUri.fsPath)) {
			const data = fs.readFileSync(projectTemplateFileUri.fsPath);
			return JSON.parse(data.toString());
		}
		return {
			type: 'network',
			url: 'https://gitee.com/AiCodeEditor/framework-template'
		};
	}

	getHighlightjs(): HighlightjsParam|undefined {
		const highlightjsFileUri = vscode.Uri.joinPath(this.dir, GlobalFileNames.highlightjs);
		this.checkFileDir(highlightjsFileUri);	
		if(fs.existsSync(highlightjsFileUri.fsPath )) {
			const data = fs.readFileSync(highlightjsFileUri.fsPath );
			return JSON.parse(data.toString());	
		}

		return;
	}

	getConfig() {
		return {
			database: this.getDatabase(),
			modelInfo: this.getModelInfo(),
			projectTemplate: this.getProjectTemplate(),
			highlightjs: this.getHighlightjs()
		};
	}

	setConfig(config: any) {
		Object.keys(config).forEach((key) => {
			const fileUri = vscode.Uri.joinPath(this.dir, GlobalFileNames[key as keyof typeof GlobalFileNames]);
			this.checkFileDir(fileUri);
			fs.writeFileSync(fileUri.fsPath , JSON.stringify(config[key], null, 2));
		});
	}

	saveHistory(tasks: Task[]) {
		const historyFileUri = vscode.Uri.joinPath(this.dir, GlobalFileNames.history);
		this.checkFileDir(historyFileUri);
		fs.writeFileSync(historyFileUri.fsPath , JSON.stringify(tasks, null, 2));
	}

	getHistory(): Task[] {
		const historyFileUri = vscode.Uri.joinPath(this.dir, GlobalFileNames.history);
		this.checkFileDir(historyFileUri);
		if(fs.existsSync(historyFileUri.fsPath)) {
			const data = fs.readFileSync(historyFileUri.fsPath);
			const history = JSON.parse(data.toString());
			return history;
		}	
		return [];
	}

	saveTask(task: Task) {
		const historyFileUri = vscode.Uri.joinPath(this.dir, GlobalFileNames.history);
		this.checkFileDir(historyFileUri);
		const history = this.getHistory();
		const index = history.findIndex((t) => t.taskId === task.taskId);
		if(index === -1) {
			history.push(task);	
		}	
		else {
			history[index] = task;	
		}
		fs.writeFileSync(historyFileUri.fsPath , JSON.stringify(history, null, 2));

		const taskFileUri = vscode.Uri.joinPath(this.dir, 'task', `${task.taskId}.json`);
		this.checkFileDir(taskFileUri);
		fs.writeFileSync(taskFileUri.fsPath , JSON.stringify(task.messages, null, 2));
	}

	getTask(taskId: string): Task|void {
		const historyFileUri = vscode.Uri.joinPath(this.dir, GlobalFileNames.history);	
		this.checkFileDir(historyFileUri);
		if(fs.existsSync(historyFileUri.fsPath )) {
			const data = fs.readFileSync(historyFileUri.fsPath );
			const history = JSON.parse(data.toString());
			const task: Task = history.find((t: Task) => t.taskId === taskId);	
			if(!task || !task.taskId) {
				return;
			}
			const taskFileUri = vscode.Uri.joinPath(this.dir, 'task', `${task.taskId}.json`);
			this.checkFileDir(taskFileUri);
			if(fs.existsSync(taskFileUri.fsPath )) {
				const taskData = fs.readFileSync(taskFileUri.fsPath );
				task.messages = JSON.parse(taskData.toString());
			}
			return task;
		}
	}

	saveTaskMessages(taskId: any, messages: LocalModelMessage[]) {
		const historyFileUri = vscode.Uri.joinPath(this.dir, GlobalFileNames.history);	
		this.checkFileDir(historyFileUri);
		const data = fs.readFileSync(historyFileUri.fsPath );
		const history = JSON.parse(data.toString());
		const task: Task = history.find((t: Task) => t.taskId === taskId);	
		if(!task || !task.taskId) {
			return;
		}
		const taskFileUri = vscode.Uri.joinPath(this.dir, 'task', `${task.taskId}.json`);
		this.checkFileDir(taskFileUri);
		fs.writeFileSync(taskFileUri.fsPath, JSON.stringify(messages, null, 2));
		return task;
  }


	static getInstance(context: vscode.ExtensionContext) {
		if(!this.instance) {
			this.instance = new GlobalStore(context);
		}
		return this.instance;
	}
	static instance: GlobalStore;

	checkFileDir(file: vscode.Uri) {
		const folderPath = path.dirname(file.fsPath);
		if (!fs.existsSync(folderPath)) {
			fs.mkdirSync(folderPath, { recursive: true });
		}
	}
}
